/**
 * Copyright(c) Live2D Inc. All rights reserved.
 *
 * Use of this source code is governed by the Live2D Open Software license
 * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
 */

#include "CubismVector2.hpp"

#include "Math/CubismMath.hpp"

namespace Live2D
{
    namespace Cubism::Framework
    {
        CubismVector2 operator+(const CubismVector2 &a, const CubismVector2 &b)
        {
            return CubismVector2(a.X + b.X, a.Y + b.Y);
        }

        CubismVector2 operator-(const CubismVector2 &a, const CubismVector2 &b)
        {
            return CubismVector2(a.X - b.X, a.Y - b.Y);
        }

        CubismVector2 operator*(const CubismVector2 &vector, const csmFloat32 scalar)
        {
            return CubismVector2(vector.X * scalar, vector.Y * scalar);
        }

        CubismVector2 operator*(const csmFloat32 scalar, const CubismVector2 &vector)
        {
            return CubismVector2(vector.X * scalar, vector.Y * scalar);
        }

        CubismVector2 operator/(const CubismVector2 &vector, const csmFloat32 scalar)
        {
            return CubismVector2(vector.X / scalar, vector.Y / scalar);
        }

        const CubismVector2 &CubismVector2::operator+=(const CubismVector2 &rhs)
        {
            X += rhs.X;
            Y += rhs.Y;

            return *this;
        }

        const CubismVector2 &CubismVector2::operator-=(const CubismVector2 &rhs)
        {
            X -= rhs.X;
            Y -= rhs.Y;

            return *this;
        }

        const CubismVector2 &CubismVector2::operator*=(const CubismVector2 &rhs)
        {
            X *= rhs.X;
            Y *= rhs.Y;

            return *this;
        }

        const CubismVector2 &CubismVector2::operator/=(const CubismVector2 &rhs)
        {
            X /= rhs.X;
            Y /= rhs.Y;

            return *this;
        }

        const CubismVector2 &CubismVector2::operator*=(const csmFloat32 scalar)
        {
            X *= scalar;
            Y *= scalar;

            return *this;
        }

        const CubismVector2 &CubismVector2::operator/=(const csmFloat32 scalar)
        {
            X /= scalar;
            Y /= scalar;

            return *this;
        }

        bool CubismVector2::operator==(const CubismVector2 &rhs) const
        {
            return (X == rhs.X) && (Y == rhs.Y);
        }

        bool CubismVector2::operator!=(const CubismVector2 &rhs) const
        {
            return !(*this == rhs);
        }

        csmFloat32 CubismVector2::GetLength() const
        {
            return CubismMath::SqrtF(X * X + Y * Y);
        }

        csmFloat32 CubismVector2::GetDistanceWith(CubismVector2 a) const
        {
            return CubismMath::SqrtF(((X - a.X) * (X - a.X)) + ((Y - a.Y) * (Y - a.Y)));
        }

        csmFloat32 CubismVector2::Dot(const CubismVector2 &a) const
        {
            return (X * a.X) + (Y * a.Y);
        }

        void CubismVector2::Normalize()
        {
            const csmFloat32 length = powf((X * X) + (Y * Y), 0.5f);

            X = X / length;
            Y = Y / length;
        }
    } // namespace Cubism::Framework
} // namespace Live2D
